/*
 * Copyright (C) 2012 TopCoder Inc., All Rights Reserved.
 */
package com.ibm.dst.capacity.services.impl;

import java.util.ArrayList;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;

import com.ibm.dst.capacity.entities.dao.ReportedStatistics;
import com.ibm.dst.capacity.entities.dao.XSeriesCapacity;

/**
 * <p>
 * XSeriesCapacityDataHandler extends from SAX DefaultHandler. It is used in importCapacityData() method of XSeriesReportServiceImpl when the import data is in XML format as the handler for callbacks from the SAX parsing of the XML file. On receiving callbacks during the sax parsing, it will create and store instance of XSeriesCapacity data from the xml data which can be retrieved from the instance.
 * </p>
 * <p>
 * Thread-Safety: This class is mutable and not thread-safe. However it is created and used as the callback handler by XSeriesReportServiceImpl internally in importCapacityData() method and not shared among threads and hence will function thread-safely.
 * </p>
 * @author fastprogrammer, TCSDEVELOPER
 * @version 1.0
 */
public class XSeriesCapacityDataHandler extends DefaultHandler {
    /**
     * <p>
     * This instance member represents the list of XSeriesCapacity instances which are created and stored in the handler instance as a part of handling the callbacks for the sax parsing of input xml data.
     *
     * Mutability: This instance member is immutable and is initialized in place. However the contents in the list are mutable.
     *
     * Instantiated In: In place in the definition.
     *
     * Used In: startDocument(), endElement() and getXSeriesCapacityDataList() methods of the class.
     *
     * Valid values: List of XSeriesCapacity with none of the elements in the list being null.
     * </p>
     */
    private final List<XSeriesCapacity> xseriesCapacityDataList = new ArrayList<XSeriesCapacity>();

    /**
     * <p>
     * This instance member represents the XSeriesCapacity that is currently being worked on and being populated with the data fetched from the sax xml parsing.
     *
     * Mutability: This instance member is mutable and is modified in the startElement() and endElement() methods.
     *
     * Instantiated In: With null initially and set to a non-null instance in startElement on encountering appropriate xml element.
     *
     * Used In: startElement(), endElement() and characters() method of the class.
     *
     * Valid values: Can take any instance of XSeriesCapacity or null value.
     * </p>
     */
    private XSeriesCapacity currentXSeriesCapacity;

    /**
     * <p>
     * This instance member represents the name of the current xml element that is under processing.
     *
     * Mutability: This instance member is mutable and is modified in the startElement() and endElement() methods.
     *
     * Instantiated In: With null initially and set to a non-null instance in startElement on encountering appropriate xml element.
     *
     * Used In: startElement(), endElement() and characters() method of the class.
     *
     * Valid values: Can take any string value for the name of the xml element or null value
     * </p>
     */
    private String currentElement;

    /**
     * <p>
     * Default empty constructor. Simply do nothing.
     * </p>
     */
    public XSeriesCapacityDataHandler() {
    }

    /**
     * <p>
     * Handles the processing of start of the xml element which the xml is being parsed. Here we simply set the currentElement instance member to the value of localName. If the localName is "XSeriesCapacityDataEntry", then we create a new instance of XSereisCapacity and assign it to currentXSeriesCapacity.
     * </p>
     * Implementation Notes:
     * =================
     *
     * currentElement = localName;
     * if( "XSeriesCapacityDataEntry".equals(localName))
     *   currentXSeriesCapacity = new XSeriesCapacity();
     *
     *
     * Parameters:
     * ==========
     * uri: the uri name if any for the startElement.
     * @param localName    the localName for the element.
     * @param qName    the qualified name for the element.
     * @param attributes    any attributes for the element.
     *
     * Return Value:
     * ============
     * None
     *
     * Exceptions:
     * ==========
     * None
     * @param localName
     * @param qName
     * @param attributes
     * @param uri
     */
    public void startElement(String uri, String localName, String qName, Attributes attributes) {
        currentElement = localName;
        if( "XSeriesCapacityDataEntry".equals(localName)) {
            currentXSeriesCapacity = new XSeriesCapacity();
        }
    }

    /**
     * <p>
     * Processes the encountering for the end of the element.
     * </p>
     * Implementation Notes:
     * =================
     *
     * if("XSeriesCapacityDataEntry".equals( localName ) ){
     *    xseriesCapacityDataList. add( currentXSeriesCapacity );
     *
     *    currentXSeriesCapacity = null;
     * }
     *
     *
     * Parameters:
     * ==========
     * @param localName    the localName for the element.
     * @param qName    the qualified name for the element.
     *
     * Return Value:
     * ============
     * None
     *
     * Exceptions:
     * ==========
     * None
     * @param localName
     * @param qName
     * @param uri
     */
    public void endElement(String uri, String localName, String qName) {
        if("XSeriesCapacityDataEntry".equals( localName ) ){
            xseriesCapacityDataList. add(currentXSeriesCapacity);
            currentXSeriesCapacity = null;
        }
    }

    /**
     * <p>
     * Callback for providing the data content in an element.
     * </p>
     * Implementation Notes:
     * ===================
     *
     * String data = new String( ch, start, length );
     *
     * If currentElement is in "Hosting-Environment", "Data-Center-Site", "Hosting-Class", "Host-Name", "Hypervisor-Version" then do the following:
     *    Fetch the corresponding instance type using the LookupDataService.getXXX() methods and match the instance by the name value and set it in currentXSeriesCapacity instance.
     *
     * Else if currentElement in "VMWare-Stats-Processing-Power-Total", "VMWare-Stats-Processing-Power-Used", "VMWare-Stats-Memory-Total", "VMWare-Stats-Memory-Used", "Measured-Statistics-Processing-Power-Average", "Measured-Statistics-Processing-Power-High", "Measured-Statistics-Processing-Power-Low", "Measured-Statistics-Memory-Average", "Measured-Statistics-Memory-Low", "Measured-Statistics-Memory-High"{
     *
     *    If currentElement is starting with VMWare-Stats-Processing*, then if currentXSeriesCapacity.reportStat is null then create a new instance of ReportedStatistics, else use the instance in currentXSeriesCapacity.reportStat and set its corresponding property value  from data string instance(after appropriate type conversion)
     *
     *    If currentElement is starting with Measured-Statistics-Processing*, then if currentXSeriesCapacity.measuredStat is null then create a new instance of MeasuredStatistics, else use the instance in currentXSeriesCapacity.measuredStat and set its corresponding property value  from data string instance(after appropriate type conversion)
     *
     * }
     *
     *
     *
     * Parameters:
     * ==========
     * ch: character data in buffer
     * start: int - the start index in the ch array.
     * length: int - the length of the content.
     *
     * Return Value:
     * ============
     * None
     *
     * Exceptions:
     * ==========
     * None
     * @param start
     * @param length
     * @param ch
     */
    public void characters(char[] ch, int start, int length) {
        String data = new String(ch, start, length);

        if ("Hosting-Environment".equals(currentElement) || "Data-Center-Site".equals(currentElement)
                || "Hosting-Class".equals(currentElement) || "Host-Name".equals(currentElement)
                || "Hypervisor-Version".equals(currentElement)) {
            //Fetch the corresponding instance type using the LookupDataService.getXXX() methods and match the instance by the name value and set it in currentXSeriesCapacity instance.
        } else if ("VMWare-Stats-Processing-Power-Total".equals(currentElement)
                || "VMWare-Stats-Processing-Power-Used".equals(currentElement)
                || "VMWare-Stats-Memory-Total".equals(currentElement)
                || "VMWare-Stats-Memory-Used".equals(currentElement)
                || "Measured-Statistics-Processing-Power-Average".equals(currentElement)
                || "Measured-Statistics-Processing-Power-High".equals(currentElement)
                || "Measured-Statistics-Processing-Power-Low".equals(currentElement)
                || "Measured-Statistics-Memory-Average".equals(currentElement)
                || "Measured-Statistics-Memory-Low".equals(currentElement)
                || "Measured-Statistics-Memory-High".equals(currentElement)) {
            if (currentElement.startsWith("VMWare-Stats-Processing")) {
                if (currentXSeriesCapacity.getReportedStat() == null) {
                    //then create a new instance of ReportedStatistics,
                    currentXSeriesCapacity.setReportedStat(new ReportedStatistics());
                } else {
                    //use the instance in currentXSeriesCapacity.reportStat and set its corresponding property value
                    //from data string instance(after appropriate type conversion)
                    
                }
            }
            if (currentElement.startsWith("Measured-Statistics-Processing")) {
                if (currentXSeriesCapacity.getMeasuredStat() == null) {
                    //create a new instance of MeasuredStatistics, 
                } else {
                    //use the instance in currentXSeriesCapacity.measuredStat and set its corresponding property value
                    //from data string instance(after appropriate type conversion)
                }
            }
        }
    }

    /**
     * <p>
     * Returns the list of XSeriesCapacity data that are stored in this instance of XSeriesCapacityDataHandler.
     * </p>
     * Implementation Notes:
     * =================
     *
     * Simply return the xseriesCapacityDataList.
     *
     * Parameters:
     * ==========
     * None
     *
     * Return Value:
     * ============
     * list of XSeriesCapacity data objects. None of the elements in the list are null. Also the list is not null
     *
     * Exceptions:
     * ==========
     * None
     * @return
     */
    public List<XSeriesCapacity> getXSeriesCapacityDataList() {
        return xseriesCapacityDataList;
    }

    /**
     * <p>
     * Callback given at the start of the parsing of the XML document. Here we simply clear the xseriesCapacityDataList.
     * </p>
     * Implementation Notes:
     * =================
     * xseriesCapacityDataList.clear();
     *
     * Parameters:
     * ==========
     * None
     *
     * Return Value:
     * ============
     * None
     *
     * Exceptions:
     * ==========
     * None
     */
    public void startDocument() {
        xseriesCapacityDataList.clear();
    }
}

